package hotel.dao.impl;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import hotel.dao.IDao;

@Component
public class DaoImpl<T> implements IDao<T> {

	@Autowired
	protected SessionFactory sessionFactory;
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findById(Class<T> clazz, int id) {
		Session session=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			return (T)session.get(clazz, id);
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return null;
	}

	@Override
	public boolean save(Object obj) {
		Session session=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			session.save(obj);
			return true;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return false;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T saveAndReturn(Object obj) {
		Session session=null;
		T newObj=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			newObj=(T)session.get(obj.getClass(), session.save(obj));
			session.getTransaction().commit();
			return newObj;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.close();
		}
		return newObj;
	}

	@Override
	public boolean update(Object obj) {
		Session session=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			session.update(obj);
			return true;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return false;
	}

	@Override
	public boolean delete(Object obj) {
		Session session=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			session.delete(obj);
			return true;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return false;
	}

	@Override
	public boolean deleteById(String upperCaseClazz, int id) {
		Session session=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			session.createQuery("delete "+upperCaseClazz+" where "+upperCaseClazz.toLowerCase()+"id = "+id).executeUpdate();
			return true;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return false;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findFirstResult(String hql) {
		Session session=sessionFactory.openSession();
		session.beginTransaction();
		T obj=(T)session.createQuery(hql).uniqueResult();
		session.getTransaction().commit();
		session.close();
		return obj;
	}

	@Override
	public boolean executeUpdate(String hql) {
		Session session=sessionFactory.openSession();
		session.beginTransaction();
		int result=session.createQuery(hql).executeUpdate();
		session.getTransaction().commit();
		session.close();
		if(result>0)
			return true;
		return false;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Object[]> sqlQuery(String sql) {
		Session session=sessionFactory.openSession();
		session.beginTransaction();
		List<Object[]> list=session.createSQLQuery(sql).list();
		session.getTransaction().commit();
		session.close();
		return list;
	}


	@Override
	public int getTotalCount(String entityName) {
		Session session=null;
		int count=-1;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			count=Integer.parseInt(session.createQuery("select count(*) from "+entityName)
					.uniqueResult().toString());
			return count;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return count;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> listAll(String entityName) {
		Session session=null;
		List<T> list=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			list=(List<T>)session.createQuery("from "+entityName).list();
			return list;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> paging(String entityName, int firstResult, int maxResult) {
		Session session=null;
		List<T> list=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			list=(List<T>)session.createQuery("from "+entityName)
					.setFirstResult(firstResult)
					.setMaxResults(maxResult)
					.list();
			return list;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> list(String hql) {
		Session session=null;
		List<T> list=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			list=(List<T>)session.createQuery(hql).list();
			return list;
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			session.getTransaction().commit();
			session.close();
		}
		return list;
	}

	@Override
	public String uniqueResult(String hql) {
		Session session=null;
		String result=null;
		try {
			session=sessionFactory.openSession();
			session.beginTransaction();
			result=session.createQuery(hql).uniqueResult().toString();
			session.getTransaction().commit();
			return result;
		}catch(Exception ex) {
			return null;
		}finally {
			session.close();
		}
	}
}